package main

import (
	"fmt"
	"time"
	"sync"
)

func main()  {
	//test1()
	//test2()
	//test3()
	//test4()
	//test5()
	//test6()
	test7()

}

//缓冲通道
func test1()  {

	ch1 := make(chan int, 5)

	go func() {
		for i:=1; i<=6; i++ {
			ch1 <- i
			fmt.Println("子G写出数据:", i)
		}
		close(ch1)
		fmt.Println("子G结束--")
	}()

	for  {
		data, ok := <- ch1

		if !ok {
			fmt.Println("数据接收完")
			break
		}
		fmt.Println("接收到数据:", data)

	}


	time.Sleep(time.Second*3)
}

//select
func test2()  {
	ch1 := make(chan int)
	ch2 := make(chan int)

	go func() {
		time.Sleep(time.Second * 3)
		ch1 <- 100
	}()

	go func() {
		time.Sleep(time.Second * 4)
		ch2 <- 200
	}()

	select {
	case data:=<- ch1:
		fmt.Println("ch1--data:", data)
	case data:=<- ch2:
		fmt.Println("ch2--data:", data)
	case <-time.After(2 * time.Second):
		fmt.Println("超时....")
	default:
		fmt.Println("默认----")



	}

}

//waitgroup
func test3()  {
	var wg sync.WaitGroup

	wg.Add(3)

	go func() {
		for i:=0; i<10; i++ {
			fmt.Println("---i:", i)
		}
		wg.Done()
	}()

	go func() {
		for j:=100; j<110; j++ {
			fmt.Println("\t######j:", j)
		}
		wg.Done()
	}()

	go func() {
		for k:=1000; k<1005; k++ {
			fmt.Println("\t\t~~~~~k:", k)
		}
		wg.Done()
	}()


	wg.Wait()
	fmt.Println("====== main over ======")

}


//lock
func test4()  {
	num := 0
	var mutext sync.Mutex

	mutext.Lock()
	fmt.Println("主携程已加锁----")
	time.Sleep(time.Second*3)
	fmt.Println("---主携程--num:", num)

	go func() {

		for i:=0; i<3; i++ {
			mutext.Lock()
			fmt.Println("g1--已经加锁")
			fmt.Println("g1--num:", num)
			num++

			mutext.Unlock()
			fmt.Println("g1--已经解锁")
		}
	}()

	mutext.Unlock()
	fmt.Println("主携程已解锁----")
	fmt.Println("---主携程--num:", num)

	time.Sleep(time.Second*3)
}


//加锁解决 共享数据安全----买票
func test5()  {
	tick := 100
	var lock sync.Mutex
	wg := sync.WaitGroup{}

	wg.Add(4)

	go sel0(&tick, &lock, &wg, "窗口1")
	go sel0(&tick, &lock, &wg, "窗口2")
	go sel0(&tick, &lock, &wg, "窗口3")
	go sel0(&tick, &lock, &wg, "窗口4")


	fmt.Println(tick)

	wg.Wait()

}

func sel0(tick *int, lock *sync.Mutex, wg *sync.WaitGroup, name string)  {

	for {
		lock.Lock()

		if *tick <= 0 {
			fmt.Println("票已经卖完---", name)
			lock.Unlock()
			break
		}

		time.Sleep(time.Millisecond * 100)

		fmt.Println(name," 卖出tick:", *tick)
		*tick--

		lock.Unlock()
	}

	wg.Done()

}


type GtData struct {
	data 	*interface{}
	lock 	*sync.Mutex
	wg 		*sync.WaitGroup
	name 	string
}


//通道   消费者/生产者 模式
func test6()  {
	ch1 := make(chan int, 10)

	var wg sync.WaitGroup
	wg.Add(4)

	go sendData(ch1,&wg, "生产者")
	go getData(ch1, &wg, "消费者01")
	go getData(ch1, &wg, "消费者02")
	go getData(ch1, &wg, "消费者03")

	wg.Wait()
}
//生产者
func sendData(ch1 chan <- int, wg *sync.WaitGroup, name string)  {
	for i:=1; i<=200; i++ {
		ch1 <- i
		fmt.Println(name, "发送数据i:", i)
	}
	close(ch1)

	wg.Done()
}
//消费者
func getData(ch1 <- chan int, wg *sync.WaitGroup, name string)  {
	for data := range ch1 {
		fmt.Println("\t", name, "接收数据i:", data)
	}
	wg.Done()
}



//通道、卖票
func test7()  {
	ch1 := make(chan int, 5)

	for i:=1; i<=3; i++ {
		go func(j int) {

			for data := range ch1 {
				fmt.Println("窗口", j, "卖出票:", data)
			}


		}(i)
	}

	for i:=100; i>0; i-- {
		ch1 <- i
	}
	close(ch1)

	time.Sleep(time.Second * 3)
	fmt.Println("======= main over ======")
}



